﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace Agile.DataAccess
{
    internal class SelectBuilder : ISelectBuilder
	{
		public SelectBuilderData Data { get; set; }
		protected ActionsHandler Actions { get; set; }
        public SelectBuilder(IDbCommand command, string name)
		{
            Data = new SelectBuilderData(command, name);
            Actions = new ActionsHandler(Data);
		}
		private IDbCommand GetPreparedDbCommand()
		{
            if (Data.PagingItemsPerPage > 0 && Data.OrderBy.Count == 0)
                throw new FluentDataException("Order by must defined when using Paging.");

            Data.Command.ClearSql.Script(Data.Command.Data.Context.Data.FluentDataProvider.GetSqlForSelectBuilder(Data, false));
            return Data.Command;
		}

        internal virtual ISelectBuilder AutoMap<TEntity>(params Expression<Func<TEntity, object>>[] ignoreProperties)
        {
            TEntity item = System.Activator.CreateInstance<TEntity>();
            Data.Item = item;
            Actions.AutoMapFieldAction(ignoreProperties);
            return this;
        }

        public virtual ISelectBuilder Where(string columnName, object value, DataTypes parameterType, int size)
		{
			Actions.WhereAction(columnName, value, parameterType, size);
			return this;
        }

        public virtual ISelectBuilder OrderBy(string columnName, string value, DataTypes parameterType, int size)
        {
            string sort = value.ToLower().Trim().Equals("asc") == false && value.ToLower().Trim().Equals("desc") == false ? "ASC" : value.Trim().ToUpper();
            Actions.OrderByAction(columnName, sort, parameterType, size);
            return this;
        }

        public ISelectBuilder Paging(int currentPage, int itemsPerPage)
        {
            Data.PagingCurrentPage = currentPage;
            Data.PagingItemsPerPage = itemsPerPage;
            return this;
        }

        public List<TEntity> QueryMany<TEntity>(Action<TEntity, IDataReader> customMapper = null)
        {
            this.AutoMap<TEntity>();
            return GetPreparedDbCommand().QueryMany<TEntity>(customMapper);
        }

        public List<TEntity> QueryMany<TEntity>(Action<TEntity, dynamic> customMapper)
        {
            this.AutoMap<TEntity>();
            return GetPreparedDbCommand().QueryMany<TEntity>(customMapper);
        }

        public TList QueryMany<TEntity, TList>(Action<TEntity, IDataReader> customMapper = null) where TList : IList<TEntity>
        {
            this.AutoMap<TEntity>();
            return GetPreparedDbCommand().QueryMany<TEntity, TList>(customMapper);
        }

        public TList QueryMany<TEntity, TList>(Action<TEntity, dynamic> customMapper) where TList : IList<TEntity>
        {
            this.AutoMap<TEntity>();
            return GetPreparedDbCommand().QueryMany<TEntity, TList>(customMapper);
        }

        public void QueryComplexMany<TEntity>(IList<TEntity> list, Action<IList<TEntity>, IDataReader> customMapper)
        {
            this.AutoMap<TEntity>();
            GetPreparedDbCommand().QueryComplexMany<TEntity>(list, customMapper);
        }

        public void QueryComplexMany<TEntity>(IList<TEntity> list, Action<IList<TEntity>, dynamic> customMapper)
        {
            this.AutoMap<TEntity>();
            GetPreparedDbCommand().QueryComplexMany<TEntity>(list, customMapper);
        }

        public TEntity QuerySingle<TEntity>(Action<TEntity, IDataReader> customMapper = null)
        {
            this.AutoMap<TEntity>();
            return GetPreparedDbCommand().QuerySingle<TEntity>(customMapper);
        }

        public TEntity QuerySingle<TEntity>(Action<TEntity, dynamic> customMapper)
        {
            this.AutoMap<TEntity>();
            return GetPreparedDbCommand().QuerySingle<TEntity>(customMapper);
        }

        public TEntity QueryComplexSingle<TEntity>(Func<IDataReader, TEntity> customMapper)
        {
            this.AutoMap<TEntity>();
            return GetPreparedDbCommand().QueryComplexSingle(customMapper);
        }

        public TEntity QueryComplexSingle<TEntity>(Func<dynamic, TEntity> customMapper)
        {
            this.AutoMap<TEntity>();
            return GetPreparedDbCommand().QueryComplexSingle(customMapper);
        }
		
	}
}
